﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using FaceSharp.Api.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace FaceSharp.Api.GraphApi
{
    public class TypedGraphBase<T> 
    {
        private readonly GenericGraphClient _genericGraphClient;
        private readonly Func<string, JObject> _jObjectResultConverter;
        private readonly Func<string, IList<T>> _typedResultConverter;
        
        public TypedGraphBase(IFacebookCore facebookCore) 
        {
            _genericGraphClient = new GenericGraphClient(facebookCore);
            _jObjectResultConverter = (rawResults) => { return JObject.Parse(rawResults); };
            _typedResultConverter = (rawResults) => { return Deserialize(rawResults); };
        }

        public JObject GetMetaData(string id)
        {
            return _genericGraphClient.GetMetaData(id, _jObjectResultConverter).Results;
        }

        public JObject MakeGraphPost(
         string id,
         Dictionary<string, string> parameters
         )
        {
            return _genericGraphClient.MakeGraphPost(id,parameters,_jObjectResultConverter).Results;
        }

        public JObject MakeGraphPost(
             string id,
             string connection,
             Dictionary<string, string> parameters
             )
        {
            return _genericGraphClient.MakeGraphPost(id,connection,parameters,_jObjectResultConverter).Results;
        }

        public IList<T> MakeGraphSeach(
            string query = null,
            string objectType = null
            )
        {
            return _genericGraphClient.MakeGraphSeach(_typedResultConverter, query, objectType).Results;
        }

        public IList<T> MakeGraphRequest(
             string id,
             string connection = null,
             IEnumerable<string> fields = null)
        {
            return _genericGraphClient.MakeGraphRequest(id, _typedResultConverter, connection, fields).Results;
        }

        public IList<T> MakeGraphRequest(
            IEnumerable<string> ids,
            IEnumerable<string> fields = null)
        {
            return _genericGraphClient.MakeGraphRequest(ids, _typedResultConverter, fields).Results;
        }
 
        /// <summary>
        /// Converts Facebook JSON results into a strongly typed object. (See Places for a good example)
        /// </summary>
        /// <param name="jsonText">Raw JSON Results</param>
        /// <returns></returns>
        public IList<T> Deserialize(string jsonText)
        {
            var json = new Newtonsoft.Json.JsonSerializer
            {
                NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
                ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace,
                MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore,
                ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore,
            };

            var results = JObject.Parse(jsonText);
            var collectionHolder = results["data"];
            if (collectionHolder != null)
            {
                IList<JToken> tokens = collectionHolder.Children().ToList();
                IList<T> typedCollection = new List<T>();
                tokens.ForEach(x => typedCollection.Add(JsonConvert.DeserializeObject<T>(x.ToString())));
                return typedCollection;
            }
            else
            {
                var sr = new StringReader(jsonText);
                var reader = new JsonTextReader(sr);
                var result = (T)json.Deserialize<T>(reader);
                reader.Close();
                IList<T> typedCollection = new List<T> {result};
                return typedCollection;
            }
        }
    }
}